import { EventMgr } from "./EventManager";
import { Msg } from "./EventMsg";

class SocketPackage
{
    public event: string;
    public data: Uint8Array;

    constructor(event: string, data: Uint8Array)
    {
        this.event = event;
        this.data = data;
    }
}


export enum NetWorkState {
    NetWorkState_NONE,
    NetWorkState_CONNECTING,
    NetWorkState_CONNECTED,
    NetWorkState_ERROR,
    NetWorkState_CLOSE,
    NetWorkState_MAX
}

class SocketEvent
{
    public createRoom: string = 'createRoom';
}

export let socketEvent: SocketEvent = new SocketEvent();


class Socket {

    private webSocket: WebSocket = null;
    private socketUrl: string = 'ws://127.0.0.1:9021';
    private netWorkState: NetWorkState = NetWorkState.NetWorkState_NONE;
    
    public initSocket(uid: number)
    {
        if (this.webSocket != null && this.netWorkState != NetWorkState.NetWorkState_CLOSE) {
            this.webSocket.close();
        }

        this.webSocket = new WebSocket(this.socketUrl, uid.toString());
        this.webSocket.onopen = this.onOpen;
        this.webSocket.onmessage = this.onMessage;
        this.webSocket.onerror = this.onError;
        this.webSocket.onclose = this.onClose;
        this.netWorkState = NetWorkState.NetWorkState_CONNECTING;
    }

    public SendData(event: string, data: Uint8Array)
    {
        let socketPackage = new SocketPackage(event, data);
        if (this.webSocket != null && this.netWorkState == NetWorkState.NetWorkState_CONNECTED) {
            this.webSocket.send(JSON.stringify(socketPackage));
        }
    }

    public CloseSocket(code?: number, reason?: string)
    {
        if (this.webSocket != null && this.netWorkState != NetWorkState.NetWorkState_CLOSE) {
            this.webSocket.close(code, reason);
        }
    }

    private onOpen(event: Event)
    {
        this.netWorkState = NetWorkState.NetWorkState_CONNECTED;
        EventMgr.raiseEvent(Msg.socketConnected);
    }

    private onMessage(event: MessageEvent)
    {
        let socketPackage: SocketPackage = JSON.parse(event.data);
        EventMgr.raiseEvent(socketPackage.event, socketPackage.data);
    }

    private onError(event: Event)
    {
        cc.error("websocket error: " + event);
    }

    private onClose(event: CloseEvent)
    {
        this.netWorkState = NetWorkState.NetWorkState_CLOSE;
        EventMgr.raiseEvent(Msg.socketClosed);
    }
}

export let socketManager: Socket = new Socket();